package com.chang.product.service.impl;

import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.chang.common.utils.PageUtils;
import com.chang.common.utils.Query;
import com.chang.common.utils.R;
import com.chang.product.entity.SkuImagesEntity;
import com.chang.product.entity.SkuInfoEntity;
import com.chang.product.entity.SpuInfoDescEntity;
import com.chang.product.feign.SeckillFeignService;
import com.chang.product.mapper.SkuInfoDao;
import com.chang.product.service.*;
import com.chang.product.vo.SeckillSkuVo;
import com.chang.product.vo.SkuItemSaleAttrVo;
import com.chang.product.vo.SkuItemVo;
import com.chang.product.vo.SpuItemAttrGroupVo;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ThreadPoolExecutor;

@Slf4j
@Service("skuInfoService")
public class SkuInfoServiceImpl extends ServiceImpl<SkuInfoDao, SkuInfoEntity> implements SkuInfoService {

    @Resource
    SkuImagesService skuImagesService;
    @Resource
    SpuInfoDescService spuInfoDescService;
    @Resource
    AttrGroupService attrGroupService;
    @Resource
    SkuSaleAttrValueService skuSaleAttrValueService;
    @Resource
    SeckillFeignService seckillFeignService;

    @Resource
    ThreadPoolExecutor threadPoolExecutor;

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<SkuInfoEntity> page = this.page(
                new Query<SkuInfoEntity>().getPage(params),
                new QueryWrapper<SkuInfoEntity>()
        );

        return new PageUtils(page);
    }

    @Override
    public void saveSkuInfo(SkuInfoEntity skuInfoEntity) {
        save(skuInfoEntity);
    }

    @Override
    public PageUtils queryPageByCondition(Map<String, Object> params) {
        LambdaQueryWrapper<SkuInfoEntity> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        String key = (String) params.get("key");
        if (StringUtils.hasLength(key)) {
            lambdaQueryWrapper.and(wrapper -> {
                wrapper.eq(SkuInfoEntity::getSkuId, key)
                        .or()
                        .like(SkuInfoEntity::getSkuName, key);
            });
        }
        String catelogId = (String) params.get("catelogId");
        if (StringUtils.hasLength(catelogId) && !"0".equalsIgnoreCase(catelogId)) {
            lambdaQueryWrapper.eq(SkuInfoEntity::getCatalogId, catelogId);
        }
        String brandId = (String) params.get("brandId");
        if (StringUtils.hasLength(brandId) && !"0".equalsIgnoreCase(brandId)) {
            lambdaQueryWrapper.eq(SkuInfoEntity::getBrandId, brandId);
        }
        String min = (String) params.get("min");
        String max = (String) params.get("max");
        if (StringUtils.hasLength(min)) {
            lambdaQueryWrapper.ge(SkuInfoEntity::getPrice, min);
        }
        if (StringUtils.hasLength(max)) {
            try {
                BigDecimal bigDecimal = new BigDecimal(max);
                if (bigDecimal.compareTo(BigDecimal.ZERO) == 1) {
                    lambdaQueryWrapper.le(SkuInfoEntity::getPrice, max);
                }
            } catch (Exception e) {
            }
        }
        IPage<SkuInfoEntity> page = this.page(
                new Query<SkuInfoEntity>().getPage(params),
                lambdaQueryWrapper
        );

        return new PageUtils(page);
    }

    @Override
    public List<SkuInfoEntity> getSkuBySpuId(Long spuId) {
        return list(new LambdaQueryWrapper<SkuInfoEntity>().eq(SkuInfoEntity::getSpuId, spuId));
    }

    @Override
    public SkuItemVo getSkuItem(Long skuId) {
        SkuItemVo skuItemVo = new SkuItemVo();

        // 异步编排
        CompletableFuture<SkuInfoEntity> infoFuture = CompletableFuture.supplyAsync(() -> {
            // 1,sku 基本信息获取
            SkuInfoEntity skuInfo = getById(skuId);
            skuItemVo.setInfo(skuInfo);
            return skuInfo;
        }, threadPoolExecutor);

        CompletableFuture<Void> saleAttrFuture = infoFuture.thenAcceptAsync(info -> {
            if (info != null) {
                // 获取spu销售属性组合
                List<SkuItemSaleAttrVo> skuItemSaleAttrVoList = skuSaleAttrValueService.getSaleAttrsBySpuId(info.getSpuId());
                skuItemVo.setSaleAttr(skuItemSaleAttrVoList);
            }
        }, threadPoolExecutor);

        CompletableFuture<Void> descFuture = infoFuture.thenAcceptAsync(info -> {
            if (info != null) {
                // 获取spu介绍
                SpuInfoDescEntity spuInfoDesc = spuInfoDescService.getById(info.getSpuId());
                skuItemVo.setDesc(spuInfoDesc);
            }
        }, threadPoolExecutor);

        CompletableFuture<Void> baseAttrFuture = infoFuture.thenAcceptAsync(info -> {
            if (info != null) {
                // 获取spu规格参数信息
                List<SpuItemAttrGroupVo> attrsVoList = attrGroupService.getAttrGroupWithAttrsBySpuId(info.getSpuId(), info.getCatalogId());
                skuItemVo.setGroupAttrs(attrsVoList);
            }
        }, threadPoolExecutor);

        CompletableFuture<Void> imageFuture = CompletableFuture.runAsync(() -> {
            // sku图片信息
            List<SkuImagesEntity> imageList = skuImagesService.getImagesBySkuId(skuId);
            skuItemVo.setImages(imageList);
        }, threadPoolExecutor);

        // 查询当前sku商品是否参加秒杀优惠
        CompletableFuture<Void> seckillFuture = CompletableFuture.runAsync(() -> {
            R skuSeckillInfo = seckillFeignService.getSkuSeckillInfo(skuId);
            if (skuSeckillInfo.getCode() == 0) {
                JSONObject data = skuSeckillInfo.getData();
                SeckillSkuVo seckillSkuVo = JSONUtil.toBean(JSONUtil.toJsonStr(data), SeckillSkuVo.class);
                skuItemVo.setSeckillSkuVo(seckillSkuVo);
            }
        }, threadPoolExecutor);
        // 阻塞式等待所有任务都完成
        CompletableFuture.allOf(saleAttrFuture, descFuture, baseAttrFuture, imageFuture, seckillFuture).join();

        log.info("skuItemVo:{}", JSONUtil.toJsonStr(skuItemVo));
        return skuItemVo;
    }

    @Override
    public Map<Long, String> getNewPrice(List<Long> skuIds) {
        Map<Long, String> map = new HashMap<>();
        List<SkuInfoEntity> skuInfoEntities = listByIds(skuIds);
        skuInfoEntities.forEach(skuInfoEntity -> {
            map.put(skuInfoEntity.getSkuId(), skuInfoEntity.getPrice().toString());
        });
        skuInfoEntities.clear();
        return map;
    }

}